// use fnv::FnvHashMap;
// use std::marked::Sized;

trait Rule{
    fn done(&self,ins:String) -> String;
}

pub struct Symbol {
}
impl Rule for Symbol {
    fn done(&self,ins:String) -> String {
        let s = ins.as_str();
        if let Some(p) = s.find("-1)-(0)+1") {
            let start = s[..p].rfind("(").unwrap();
            let r = s[..start].to_string()+&s[start+1..p]+&s[p+9..];
            r
        } else if let Some(p) = s.find(" - 1)-(0)+1") {
            let start = s[..p].rfind("(").unwrap();
            let r = s[..start].to_string()+&s[start+1..p]+&s[p+11..];
            r
        } else {
            ins
        }
    }
}

pub struct Integer {
}

impl Rule for Integer {

    fn done(&self,ins:String) -> String {
        let s = ins.as_str();
        if let Some(p) = s.find(")-(0)+1") {
            let start = s[..p].rfind("(").unwrap();
            if let Ok(i) = s[start+1..p].parse::<u32>() {
                let r = s[..start].to_string()+&(i+1).to_string()+&s[p+7..];
                r
            } else {
                ins
            }
        } else {
            ins
        }
    }    
}

pub struct Bool {
}

impl Rule for Bool {
    fn done(&self,ins:String) -> String {
        let s = ins.as_str();
        if let Some(p) = s.find("Bool'0'") {
            let r = s[..p].to_string()+"False"+&s[p+7..];
            r
        } else if let Some(p) = s.find("Bool'1'") {
            let r = s[..p].to_string()+"True"+&s[p+7..];
            r
        } else {
            ins
        }
    }    
}

pub struct Others {}
impl Rule for Others {
    fn done(&self,ins:String) -> String {
        let s = ins.as_str();
        let mut result = ins.clone();
        if let Some(p) = s.find("others") {
            if let Some(start) = s[..p].rfind("(") {
                if let Some(end) = s[p..].find(")") {
                    result = s[..start].to_string()+&s[p+end+1..];
                }
            }
        } 
        result
    }    
}


pub struct Rules {
}

impl Rules {
    pub fn done(&self,ins:String) -> String {
        let mut result = ins.to_owned();
        let i = Integer{};
        let s = Symbol{};
        let b = Bool{};
        let o = Others{};

        result = i.done(result.clone());
        result = s.done(result.clone());
        result = b.done(result.clone());
        result = o.done(result.clone());
        
        result
    }
}
pub fn reg_test() {
    let r = Rules{};
    let s = Symbol{};
    let i = Integer{};
    let ins = String::from("(A-1)-(0)+1");
    // println!("{}",i.done(ins.clone()));
    // println!("{}",s.done(i.done(ins.clone())));
    println!("{}",r.done(ins.clone()));
    
    let ins = String::from("((A-1)-(0)+1)");
    println!("{}",r.done(ins));
    let ins = String::from("((63)-(0)+1 bits)");
    println!("{}",r.done(ins));
    
}